<?php

class Adept_Template_Component_Tag extends Adept_Template_Tag
{

    protected $componentClass;
    protected $strictChildren;
    protected $browserEvents = array();

    const BOOLEAN = 'boolean';

    public function getElementRefCode()
    {
        return parent::getElementRefCode() . "->getChild('"
        . $this->getNodeId() . "')";
    }

    public function getNodeId()
    {
        if ($this->hasAttribute('id')) {
            if ($this->getAttribute('id') instanceof Adept_Template_Attribute_Constant) {
                return $this->getAttributeValue('id');
            }
        }
        return parent::getNodeId();
    }

    public function prepare()
    {
        $this->retriveParameters();
        parent::prepare();
    }

    protected function generateSetters($var, $writer)
    {
        foreach ($this->tagInfo->getAttributes() as $name => $options) {

            $attribute = $this->getAttribute($name);
            if ($attribute) {
                $boolean = isset($options[self::BOOLEAN]) && $options[self::BOOLEAN];

                if ($attribute instanceof Adept_Template_Attribute_Expression) {
                    $writer->writePhp("{$var}->setBindingString(");
                    $writer->writePhpLiteral($name);
                    $writer->writePhp(', ');
                    $attribute->generateBindingString($writer);
                    $writer->writePhp("); \n");
                } else {

                    $writer->writePhp("{$var}->set" . ucfirst($name) . "(");

                    if ($boolean) {
                        $writer->writePhp($this->getBoolAttributeValue($name) ? 'true' : 'false');
                    } else {
                        $writer->writePhpLiteral($this->getAttributeValue($name));
                    }

                    $writer->writePhp("); \n");
                }
            }
        }
    }

    public function generateBrowserEvents($ref, $writer)
    {
        foreach ($this->browserEvents as $name) {
            if ($attribute = $this->getAttribute($name)) {
                if ($attribute instanceof Adept_Template_Attribute_Expression) {
                    $writer->writePhp("{$ref}->setBindingString(");
                    $writer->writePhpLiteral($name);
                    $writer->writePhp(', ');
                    $attribute->generateBindingString($writer);
                    $writer->writePhp("); \n");
                } else {
                    $writer->writePhp("{$ref}->setBrowserEvent(");
                    $writer->writePhpLiteral($name);
                    $writer->writePhp(", ");
                    $writer->writePhpLiteral($this->getAttributeValue($name));
                    $writer->writePhp("); \n");
                }
            }
        }
    }

    public function generateBegin($writer)
    {

        $var = $writer->generateVar();
        $writer->writePhp("{$var} = new {$this->componentClass}();\n");

        $writer->writePhp($this->parent->getElementRefCode());
        $writer->writePhp("->addChild({$var}, ");

        $writer->writePhpLiteral($this->getNodeId());
        $writer->writePhp(");\n");

        if ($this->hasAttribute('this')) {
            $writer->writePhp("{$var}->setBindingThis(");
            $this->getAttribute('this')->generate($writer);
            $writer->writePhp("); \n");
        }

        $this->generateSetters($var, $writer);
        
        $this->generateBrowserEvents($var, $writer);

    }

    public function generateChildren($writer)
    {
        if (is_array($this->strictChildren) && count($this->strictChildren) > 0) {
            $allowedChildClasses = $this->strictChildren;
            $children = array();
            foreach ($this->getChildren() as $key => $child) {
                if (in_array(get_class($child), $allowedChildClasses)) {
                    $children[] = $child;
                }
            }
        } else {
            $children = $this->getChildren();
        }
        foreach ($children as $child) {
            $child->generate($writer);
        }
    }

    public function generateEnd($writer)
    {

    }

    public function retriveParameters()
    {
        $this->componentClass = $this->tagInfo->getParameter('component');
        if ($this->componentClass == null) {
            throw new Adept_Template_Exception("'component' parameter not defined", array(), $this->getLocation());
        }
        $this->strictChildren = $this->tagInfo->getParameter('strictChildren');

        $this->browserEvents = $this->tagInfo->getParameter('browserEvents', array());

    }

}